<div class="tmd-doc">
<h1 class="tmd-header-1">
Concurrency Synchronization Techniques Provided in the <code class="tmd-code-span">sync</code> Standard Package
</h1>
<p></p>
<div class="tmd-usual">
The <a href="channel-use-cases.html">channel use cases</a> article introduces many use cases in which channels are used to do data synchronizations among goroutines. In fact, channels are not the only synchronization techniques provided in Go. There are some other synchronization techniques supported by Go. For some specified circumstances, using the synchronization techniques other than channel are more efficient and readable than using channels. Below will introduce the synchronization techniques provided in the <code class="tmd-code-span">sync</code> standard package.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
The <code class="tmd-code-span">sync</code> standard package provides several types which can be used to do synchronizations for some specialized circumstances and guarantee some specialized memory orders. For the specialized circumstances, these techniques are more efficient, and look cleaner, than the channel ways.
</div>
<p></p>
<div class="tmd-usual">
<span class="tmd-italic">(Please note, to avoid abnormal behaviors, it is best never to copy the values of the types in the <code class="tmd-code-span">sync</code> standard package.)</span>
</div>
<p></p>
<h3 id="waitgroup" class="tmd-header-3">
The <code class="tmd-code-span">sync.WaitGroup</code> Type
</h3>
<p></p>
<div class="tmd-usual">
Each <code class="tmd-code-span">sync.WaitGroup</code> value maintains a counter internally. The initial value of the counter is zero.
</div>
<p></p>
<div class="tmd-usual">
The <code class="tmd-code-span">*WaitGroup</code> type has <a href="https://golang.org/pkg/sync/#WaitGroup">three methods</a>: <code class="tmd-code-span">Add(delta int)</code>, <code class="tmd-code-span">Done()</code> and <code class="tmd-code-span">Wait()</code>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
For an addressable <code class="tmd-code-span">WaitGroup</code> value <code class="tmd-code-span">wg</code>,
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
we can call the <code class="tmd-code-span">wg.Add(delta)</code> method to change the counter value maintained by <code class="tmd-code-span">wg</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the method call <code class="tmd-code-span">wg.Done()</code> is totally equivalent to the method call <code class="tmd-code-span">wg.Add(-1)</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
if a call <code class="tmd-code-span">wg.Add(delta)</code> (or <code class="tmd-code-span">wg.Done()</code>) modifies the counter maintained by <code class="tmd-code-span">wg</code> to negative,  panic will happen.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
when a goroutine calls <code class="tmd-code-span">wg.Wait()</code>,
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
if the counter maintained by <code class="tmd-code-span">wg</code> is already zero, then the call <code class="tmd-code-span">wg.Wait()</code> can be viewed as a no-op.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
otherwise (the counter is positive), the goroutine will enter blocking state. It will enter running state again (a.k.a., the call <code class="tmd-code-span">wg.Wait()</code> returns) when another goroutine modifies the counter to zero, generally by calling <code class="tmd-code-span">wg.Done()</code>.
</div>
</li>
</ul>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Please note that <code class="tmd-code-span">wg.Add(delta)</code>, <code class="tmd-code-span">wg.Done()</code> and <code class="tmd-code-span">wg.Wait()</code> are shorthands of <code class="tmd-code-span">(&amp;wg).Add(delta)</code>, <code class="tmd-code-span">(&amp;wg).Done()</code> and <code class="tmd-code-span">(&amp;wg).Wait()</code>, respectively.
</div>
<p></p>
<div class="tmd-usual">
Generally, a <code class="tmd-code-span">WaitGroup</code> value is used for the scenario that one goroutine waits until all of several other goroutines finish their respective jobs. An example:
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"log"
	"math/rand"
	"sync"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano()) // needed before Go 1.20

	const N = 5
	var values [N]int32

	var wg sync.WaitGroup
	wg.Add(N)
	for i := 0; i &lt; N; i++ {
		i := i
		go func() {
			values[i] = 50 + rand.Int31n(50)
			log.Println("Done:", i)
			wg.Done() // &lt;=&gt; wg.Add(-1)
		}()
	}

	wg.Wait()
	// All elements are guaranteed to be
	// initialized now.
	log.Println("values:", values)
}
</code></pre>
<p></p>
<div class="tmd-usual">
In the above example, the main goroutine waits until all other <code class="tmd-code-span">N</code> goroutines have populated their respective element value in <code class="tmd-code-span">values</code> array. Here is one possible output result:
</div>
<pre class="tmd-code output">
Done: 4
Done: 1
Done: 3
Done: 0
Done: 2
values: [71 89 50 62 60]
</pre>
<p></p>
<div class="tmd-usual">
We can split the only <code class="tmd-code-span">Add</code> method call in the above example into multiple ones.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">...
	var wg sync.WaitGroup
	for i := 0; i &lt; N; i++ {
		wg.Add(1) // will be invoked N times
		i := i
		go func() {
			values[i] = 50 + rand.Int31n(50)
			wg.Done()
		}()
	}
...
</code></pre>
<p></p>
<div class="tmd-usual">
The <code class="tmd-code-span">Wait</code> method can be called in multiple goroutines. When the counter becomes zero, all of them will be notified, in a broadcast way.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">func main() {
	rand.Seed(time.Now().UnixNano()) // needed before Go 1.20

	const N = 5
	var values [N]int32

	var wgA, wgB sync.WaitGroup
	wgA.Add(N)
	wgB.Add(1)

	for i := 0; i &lt; N; i++ {
		i := i
		go func() {
			wgB.Wait() // wait a notification
			log.Printf("values[%v]=%v \n", i, values[i])
			wgA.Done()
		}()
	}

	// The loop is guaranteed to finish before
	// any above wg.Wait calls returns.
	for i := 0; i &lt; N; i++ {
		values[i] = 50 + rand.Int31n(50)
	}
	// Make a broadcast notification.
	wgB.Done()
	wgA.Wait()
}
</code></pre>
<p></p>
<div class="tmd-usual">
A <code class="tmd-code-span">WaitGroup</code> value can be reused after one call to its <code class="tmd-code-span">Wait</code> method returns. But please note that each <code class="tmd-code-span">Add</code> method call with a positive delta that occurs when the counter is zero must happen before any <code class="tmd-code-span">Wait</code> call starts, otherwise, data races may happen.
</div>
<p></p>
<h3 id="once" class="tmd-header-3">
The <code class="tmd-code-span">sync.Once</code> Type
</h3>
<p></p>
<div class="tmd-usual">
A <code class="tmd-code-span">*sync.Once</code> value has a <code class="tmd-code-span">Do(f func())</code> method, which takes a solo parameter with type <code class="tmd-code-span">func()</code>.
</div>
<p></p>
<div class="tmd-usual">
For an addressable <code class="tmd-code-span">Once</code> value <code class="tmd-code-span">o</code>, the method call <code class="tmd-code-span">o.Do()</code>, which is a shorthand of <code class="tmd-code-span">(&amp;o).Do()</code>, can be concurrently executed multiple times, in multiple goroutines. The arguments of these <code class="tmd-code-span">o.Do()</code> calls should (but are not required to) be the same function value.
</div>
<p></p>
<div class="tmd-usual">
Among these <code class="tmd-code-span">o.Do</code> method calls, only exact one argument function will be invoked. The invoked argument function is guaranteed to exit before any <code class="tmd-code-span">o.Do</code> method call returns. In other words, the code in the invoked argument function is guaranteed to be executed before any <code class="tmd-code-span">o.Do</code> method call returns.
</div>
<p></p>
<div class="tmd-usual">
Generally, a <code class="tmd-code-span">Once</code> value is used to ensure that a piece of code will be executed exactly once in concurrent programming.
</div>
<p></p>
<div class="tmd-usual">
An example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"log"
	"sync"
)

func main() {
	log.SetFlags(0)

	x := 0
	doSomething := func() {
		x++
		log.Println("Hello")
	}

	var wg sync.WaitGroup
	var once sync.Once
	for i := 0; i &lt; 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			once.Do(doSomething)
			log.Println("world!")
		}()
	}

	wg.Wait()
	log.Println("x =", x) // x = 1
}
</code></pre>
<p></p>
<div class="tmd-usual">
In the above example, <code class="tmd-code-span">Hello</code> will be printed once, but <code class="tmd-code-span">world!</code> will be printed five times. And <code class="tmd-code-span">Hello</code> is guaranteed to be printed before all five <code class="tmd-code-span">world!</code>.
</div>
<p></p>
<h3 id="mutex" class="tmd-header-3">
The <code class="tmd-code-span">sync.Mutex</code> and <code class="tmd-code-span">sync.RWMutex</code> Types
</h3>
<p></p>
<div class="tmd-usual">
Both of the <code class="tmd-code-span">*sync.Mutex</code> and <code class="tmd-code-span">*sync.RWMutex</code> types implement <a href="https://golang.org/pkg/sync/#Locker">the <code class="tmd-code-span">sync.Locker</code> interface</a>. So they both have two methods, <code class="tmd-code-span">Lock</code> and <code class="tmd-code-span">Unlock</code>, to prevent multiple data users from using a piece of data concurrently.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
Besides the <code class="tmd-code-span">Lock</code> and <code class="tmd-code-span">Unlock</code> methods, the <code class="tmd-code-span">*RWMutex</code> type has two other methods, <code class="tmd-code-span">RLock</code> and <code class="tmd-code-span">RUnlock</code>, to avoid some data users (either writers or readers) and one data writer using a piece of data at the same time but allow some data readers to access the piece of data at the same time.
</div>
<p></p>
<div class="tmd-usual">
<span class="tmd-italic">(Note, here the terminologies <span class="tmd-bold"></span></span><span class="tmd-bold"> data reader <span class="tmd-italic"></span></span><span class="tmd-italic"> and <span class="tmd-bold"></span></span><span class="tmd-bold"> data writer <span class="tmd-italic"></span></span><span class="tmd-italic">should not be interpreted from literal. They are just used for explanation purpose. A data reader might modify data and a data writer might only read data.)</span>
</div>
<p></p>
<div class="tmd-usual">
A <code class="tmd-code-span">Mutex</code> value is often called a mutual exclusion lock. A zero <code class="tmd-code-span">Mutex</code> value is an unlocked mutex. A <code class="tmd-code-span">Mutex</code> value can only be locked when it is in unlocked status. In other words, once an addressable <code class="tmd-code-span">Mutex</code> value <code class="tmd-code-span">m</code> is locked successfully (a.k.a., a <code class="tmd-code-span">m.Lock()</code> method call returns), a new attempt by a goroutine to lock the <code class="tmd-code-span">Mutex</code> value will make the goroutine enter blocking state, until the <code class="tmd-code-span">Mutex</code> value is unlocked (through a later <code class="tmd-code-span">m.Unlock()</code> call).
</div>
<p></p>
<div class="tmd-usual">
Please note that <code class="tmd-code-span">m.Lock()</code> and <code class="tmd-code-span">m.Unlock()</code> are shorthands of <code class="tmd-code-span">(&amp;m).Lock()</code> and <code class="tmd-code-span">(&amp;m).Unlock()</code>, respectively.
</div>
<p></p>
<div class="tmd-usual">
An example of using <code class="tmd-code-span">sync.Mutex</code>:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"runtime"
	"sync"
)

type Counter struct {
	m sync.Mutex
	n uint64
}

func (c *Counter) Value() uint64 {
	c.m.Lock()
	defer c.m.Unlock()
	return c.n
}

func (c *Counter) Increase(delta uint64) {
	c.m.Lock()
	c.n += delta
	c.m.Unlock()
}

func main() {
	var c Counter
	for i := 0; i &lt; 100; i++ {
		go func() {
			for k := 0; k &lt; 100; k++ {
				c.Increase(1)
			}
		}()
	}

	// The loop is just for demo purpose.
	for c.Value() &lt; 10000 {
		runtime.Gosched()
	}
	fmt.Println(c.Value()) // 10000
}
</code></pre>
<p></p>
<div class="tmd-usual">
In the above example, a <code class="tmd-code-span">Counter</code> value uses a <code class="tmd-code-span">Mutex</code> field to guarantee that the <code class="tmd-code-span">n</code> field of the <code class="tmd-code-span">Counter</code> value will be never used by multiple goroutines at the same time.
</div>
<p></p>
<div class="tmd-usual">
A <code class="tmd-code-span">RWMutex</code> value is often called a reader+writer mutual exclusion lock. It has two locks, the write lock and the read lock. The locks of a zero <code class="tmd-code-span">RWMutex</code> value are both unlocked. For an addressable <code class="tmd-code-span">RWMutex</code> value <code class="tmd-code-span">rwm</code>, data writers can lock the write lock of <code class="tmd-code-span">rwm</code> through <code class="tmd-code-span">rwm.Lock()</code> method calls, and data readers can lock the read lock of <code class="tmd-code-span">rwm</code> through <code class="tmd-code-span">rwm.RLock()</code> method calls. Method calls <code class="tmd-code-span">rwm.Unlock()</code> and <code class="tmd-code-span">rwm.RUnlock()</code> are used to unlock the write and read locks of <code class="tmd-code-span">rwm</code>. The read lock of <code class="tmd-code-span">rwm</code> maintains a lock count, which increases by one when <code class="tmd-code-span">rwm.Lock()</code> is called successfully and decreases by one when <code class="tmd-code-span">rwm.Unlock()</code> is called successfully. A zero lock count means the read lock is in unlocked status and a non-zero one (must be larger than one) means the read lock is locked.
</div>
<p></p>
<div class="tmd-usual">
Please note that <code class="tmd-code-span">rwm.Lock()</code>, <code class="tmd-code-span">rwm.Unlock()</code>, <code class="tmd-code-span">rwm.RLock()</code> and <code class="tmd-code-span">rwm.RUnlock()</code> are shorthands of <code class="tmd-code-span">(&amp;m).Lock()</code>, <code class="tmd-code-span">(&amp;m).Unlock()</code>, <code class="tmd-code-span">(&amp;m).RLock()</code> and <code class="tmd-code-span">(&amp;m).RUnlock()</code>, respectively.
</div>
<p></p>
<div class="tmd-usual">
For an addressable <code class="tmd-code-span">RWMutex</code> value <code class="tmd-code-span">rwm</code>, the following rules exist.
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
The write lock of <code class="tmd-code-span">rwm</code> may be locked only if neither of the read lock and write lock of <code class="tmd-code-span">rwm</code> is in locked status. In other words, the write lock of <code class="tmd-code-span">rwm</code> may only be held by at most one writer at any given time, and the read lock and write lock of <code class="tmd-code-span">rwm</code> may not be held at the same time.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
When the write lock of <code class="tmd-code-span">rwm</code> is in locked status, any newer attempts to lock the write lock or the read lock of <code class="tmd-code-span">rwm</code> will be blocked until the initial write lock is unlocked.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
When the read lock of <code class="tmd-code-span">rwm</code> is in locked status, any newer attempts to lock the write lock will be blocked until the read lock is unlocked. However, newer attempts to lock the read lock will succeed as long as the attempts are performed before any blocked attempts to lock the write lock (see the next rule for details). In other words, the read lock may be held by more than one readers at a time. The read lock will return to unlocked status when its lock count returns to zero.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Assume the read lock of the value <code class="tmd-code-span">rwm</code> is in locked status now, to avoid endless read locking, any newer attempts to lock the read lock after the a being blocked attempt to lock the write lock will be blocked.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Assume the write lock of the value <code class="tmd-code-span">rwm</code> is in locked status now, for the official standard Go compiler, to avoid endless write locking, the attempts to lock the read lock before releasing the write lock will succeed for sure once the write lock is unlocked, even if some of the attempts are made after some still being blocked attempts to lock the write lock.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
The last two rules are to ensure both readers and writers have chances to acquire locks.
</div>
<p></p>
<div class="tmd-usual">
Please note, locks are not bound to goroutines. A lock may be locked in one goroutine and unlocked in another one later. In other words, a lock doesn't know which goroutine successfully locked or unlocked it.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
The type of the <code class="tmd-code-span">m</code> field of the <code class="tmd-code-span">Counter</code> type in the last example can be changed to <code class="tmd-code-span">sync.RWMutex</code>, as the following code shows, to get a better performance when the <code class="tmd-code-span">Value</code> method is called very frequently but the <code class="tmd-code-span">Increase</code> method is called not frequently.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">...
type Counter struct {
	//m sync.Mutex
	m sync.RWMutex
	n uint64
}

func (c *Counter) Value() uint64 {
	//c.m.Lock()
	//defer c.m.Unlock()
	c.m.RLock()
	defer c.m.RUnlock()
	return c.n
}
...
</code></pre>
<p></p>
<div class="tmd-usual">
Another use scenario of <code class="tmd-code-span">sync.RWMutex</code> values is to slice a write job into several small ones. Please read the next section for an example.
</div>
<p></p>
<div class="tmd-usual">
By the last two rules mentioned above, the following program is very possible to output <code class="tmd-code-span">abdc</code>.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"time"
	"sync"
)

func main() {
	var m sync.RWMutex
	go func() {
		m.RLock()
		fmt.Print("a")
		time.Sleep(time.Second)
		m.RUnlock()
	}()
	go func() {
		time.Sleep(time.Second * 1 / 4)
		m.Lock()
		fmt.Print("b")
		time.Sleep(time.Second)
		m.Unlock()
	}()
	go func() {
		time.Sleep(time.Second * 2 / 4)
		m.Lock()
		fmt.Print("c")
		m.Unlock()
	}()
	go func () {
		time.Sleep(time.Second * 3 / 4)
		m.RLock()
		fmt.Print("d")
		m.RUnlock()
	}()
	time.Sleep(time.Second * 3)
	fmt.Println()
}
</code></pre>
<p></p>
<div class="tmd-usual">
Please note, the above example is only for explanation purpose. It uses <code class="tmd-code-span">time.Sleep</code> calls to do concurrency synchronizations, which is <a href="concurrent-common-mistakes.html#sleep">a bad practice for production code</a>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
<code class="tmd-code-span">sync.Mutex</code> and <code class="tmd-code-span">sync.RWMutex</code> values can also be used to make notifications, though there are many other better ways to do the same job. Here is an example which makes a notification by using a <code class="tmd-code-span">sync.Mutex</code> value.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var m sync.Mutex
	m.Lock()
	go func() {
		time.Sleep(time.Second)
		fmt.Println("Hi")
		m.Unlock() // make a notification
	}()
	m.Lock() // wait to be notified
	fmt.Println("Bye")
}
</code></pre>
<p></p>
<div class="tmd-usual">
In the above example, the text <code class="tmd-code-span">Hi</code> is guaranteed to be printed before the text <code class="tmd-code-span">Bye</code>. About the memory order guarantees made by <code class="tmd-code-span">sync.Mutex</code> and <code class="tmd-code-span">sync.RWMutex</code> values, please read <a href="memory-model.html#mutex">memory order guarantees in Go</a>.
</div>
<p></p>
<p></p>
<h3 id="cond" class="tmd-header-3">
The <code class="tmd-code-span">sync.Cond</code> Type
</h3>
<p></p>
<div class="tmd-usual">
The <code class="tmd-code-span">sync.Cond</code> type provides an efficient way to do notifications among goroutines.
</div>
<p></p>
<div class="tmd-usual">
Each <code class="tmd-code-span">sync.Cond</code> value holds a <code class="tmd-code-span">sync.Locker</code> field with name <code class="tmd-code-span">L</code>. The field value is often a value of type <code class="tmd-code-span">*sync.Mutex</code> or <code class="tmd-code-span">*sync.RWMutex</code>.
</div>
<p></p>
<div class="tmd-usual">
The <code class="tmd-code-span">*sync.Cond</code> type has <a href="https://golang.org/pkg/sync/#Cond">three methods</a>: <code class="tmd-code-span">Wait()</code>, <code class="tmd-code-span">Signal()</code> and <code class="tmd-code-span">Broadcast()</code>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
Each <code class="tmd-code-span">sync.Cond</code> value also maintains a FIFO (first in first out) waiting goroutine queue. For an addressable <code class="tmd-code-span">sync.Cond</code> value <code class="tmd-code-span">c</code>,
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">c.Wait()</code> must be called when <code class="tmd-code-span">c.L</code> is locked, otherwise, a <code class="tmd-code-span">c.Wait()</code> will cause panic. A <code class="tmd-code-span">c.Wait()</code> call will
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
first push the current caller goroutine into the waiting goroutine queue maintained by <code class="tmd-code-span">c</code>,
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
then call <code class="tmd-code-span">c.L.Unlock()</code> to unlock/unhold the lock <code class="tmd-code-span">c.L</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">

</div>
<div class="tmd-base">
<div class="tmd-usual">
then make the current caller goroutine enter blocking state. <span class="tmd-italic">&lt;sup&gt;(1)&lt;/sup}</span>
</div>
<p></p>
<div class="tmd-usual">
<span class="tmd-italic">(The caller goroutine will be unblocked by another goroutine through calling <code class="tmd-code-span">c.Signal()</code> or <code class="tmd-code-span">c.Broadcast()</code> later.)</span>
</div>
<p></p>
<div class="tmd-usual">
Once the caller goroutine is unblocked and enters running state again, <code class="tmd-code-span">c.L.Lock()</code> will be called (in the resumed <code class="tmd-code-span">c.Wait()</code> call) to try to lock and hold the lock <code class="tmd-code-span">c.L</code> again, The <code class="tmd-code-span">c.Wait()</code> call will exit after the <code class="tmd-code-span">c.L.Lock()</code> call returns.
</div>
</div>
</li>
</ol>
<p></p>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
a <code class="tmd-code-span">c.Signal()</code> call will unblock the first goroutine in (and remove it from) the waiting goroutine queue maintained by <code class="tmd-code-span">c</code>, if the queue is not empty.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
a <code class="tmd-code-span">c.Broadcast()</code> call will unblock all the goroutines in (and remove them from) the waiting goroutine queue maintained by <code class="tmd-code-span">c</code>, if the queue is not empty.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Please note that <code class="tmd-code-span">c.Wait()</code>, <code class="tmd-code-span">c.Signal()</code> and <code class="tmd-code-span">c.Broadcast()</code> are shorthands of <code class="tmd-code-span">(&amp;c).Wait()</code>, <code class="tmd-code-span">(&amp;c).Signal()</code> and <code class="tmd-code-span">(&amp;c).Broadcast()</code>, respectively.
</div>
<p></p>
<div class="tmd-usual">
<code class="tmd-code-span">c.Signal()</code> and <code class="tmd-code-span">c.Broadcast()</code> are often used to notify the status of a condition is changed, Generally, <code class="tmd-code-span">c.Wait()</code> should be called in a loop of checking whether or not a condition has got satisfied.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
In an idiomatic <code class="tmd-code-span">sync.Cond</code> use case, generally, one goroutine waits for changes of a certain condition, and some other goroutines change the condition and send notifications. Here is an example:
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano()) // needed before Go 1.20

	const N = 10
	var values [N]string

	cond := sync.NewCond(&amp;sync.Mutex{})

	for i := 0; i &lt; N; i++ {
		d := time.Second * time.Duration(rand.Intn(10)) / 10
		go func(i int) {
			time.Sleep(d) // simulate a workload

			// Changes must be made when
			// cond.L is locked.
			cond.L.Lock()
			values[i] = string('a' + i)

			// Notify when cond.L lock is locked.
			cond.Broadcast()
			cond.L.Unlock()

			// "cond.Broadcast()" can also be put
			// here, when cond.L lock is unlocked.
			//cond.Broadcast()
		}(i)
	}

	// This function must be called when
	// cond.L is locked.
	checkCondition := func() bool {
		fmt.Println(values)
		for i := 0; i &lt; N; i++ {
			if values[i] == "" {
				return false
			}
		}
		return true
	}

	cond.L.Lock()
	defer cond.L.Unlock()
	for !checkCondition() {
		// Must be called when cond.L is locked.
		cond.Wait()
	}
}
</code></pre>
<p></p>
<div class="tmd-usual">
One possible output:
</div>
<pre class="tmd-code output">
[         ]
[     f    ]
[  c   f    ]
[  c   f  h  ]
[ b c   f  h  ]
[a b c   f  h  j]
[a b c   f g h i j]
[a b c  e f g h i j]
[a b c d e f g h i j]
</pre>
<p></p>
<div class="tmd-usual">
For there is only one goroutine (the main goroutine) waiting to be unblocked in this example, the <code class="tmd-code-span">cond.Broadcast()</code> call can be replaced with <code class="tmd-code-span">cond.Signal()</code>. As the comments suggest, <code class="tmd-code-span">cond.Broadcast()</code> and <code class="tmd-code-span">cond.Signal()</code> are not required to be called when <code class="tmd-code-span">cond.L</code> is locked.
</div>
<p></p>
<div class="tmd-usual">
To avoid data races, each of the ten parts of the user defined condition should only be modified when <code class="tmd-code-span">cond.L</code> is locked. The <code class="tmd-code-span">checkCondition</code> function and the <code class="tmd-code-span">cond.Wait</code> method should be also called when <code class="tmd-code-span">cond.L</code> is locked.
</div>
<p></p>
<div class="tmd-usual">
In fact, for the above specified example, the <code class="tmd-code-span">cond.L</code> field can also be a <code class="tmd-code-span">*sync.RWMutex</code> value, and each of the ten parts of the user defined condition can be modified when the read lock of <code class="tmd-code-span">cond.L</code> is held, just as the following code shows:
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">...
	cond := sync.NewCond(&amp;sync.RWMutex{})
	cond.L.Lock()

	for i := 0; i &lt; N; i++ {
		d := time.Second * time.Duration(rand.Intn(10)) / 10
		go func(i int) {
			time.Sleep(d)
			cond.L.(*sync.RWMutex).RLock()
			values[i] = string('a' + i)
			cond.L.(*sync.RWMutex).RUnlock()
			cond.Signal()
		}(i)
	}
...
</code></pre>
<p></p>
<div class="tmd-usual">
In the above example, the <code class="tmd-code-span">sync.RWMutex</code> value is used unusually. Its read lock is held by some goroutines which modify array elements, and its write lock is used by the main goroutine to read array elements.
</div>
<p></p>
<div class="tmd-usual">
The user defined condition monitored by a <code class="tmd-code-span">Cond</code> value can be a void. For such cases, the <code class="tmd-code-span">Cond</code> value is used for notifications purely. For example, the following program will print <code class="tmd-code-span">abc</code> or <code class="tmd-code-span">bac</code>.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"sync"
)

func main() {
	wg := sync.WaitGroup{}
	wg.Add(1)
	cond := sync.NewCond(&amp;sync.Mutex{})
	cond.L.Lock()
	go func() {
		cond.L.Lock()
		go func() {
			cond.L.Lock()
			cond.Broadcast()
			cond.L.Unlock()
		}()
		cond.Wait()
		fmt.Print("a")
		cond.L.Unlock()
		wg.Done()
	}()
	cond.Wait()
	fmt.Print("b")
	cond.L.Unlock()
	wg.Wait()
	fmt.Println("c")
}
</code></pre>
<p></p>
<div class="tmd-usual">
If it needs, multiple <code class="tmd-code-span">sync.Cond</code> values can share the same <code class="tmd-code-span">sync.Locker</code>. However, such cases are rare in practice.
</div>
<p></p>
</div>
